package com.myraff.viz;

import java.util.ArrayList;

public abstract class Chart {
	
	String chart_type;
	
	int[] raw_data;
	protected int[] final_data;
	
	String title;
	
	int image_width = 600;
	int image_height = 450;
	
	/* These are the axes that are declared with chxt */
	ArrayList<String> axes;
	
	/* These are the values that are given for each of the above */
	ArrayList<Ntuple<String>> axes_labels;
	
	/* These are the positions we'll use */
	ArrayList<Ntuple<Integer>> axes_positions;
	
	/* These are the axes ranges */
	ArrayList<Ntuple<Integer>> axes_ranges;
	
	/* These are the axes scalings */
	ArrayList<Ntuple<Integer>> axes_scalings;
	
	public Chart(String myType, int[] myData) {
		chart_type = myType;
		raw_data = myData;
		
		axes = new ArrayList<String>();
		axes_labels = new ArrayList<Ntuple<String>>();
		axes_positions = new ArrayList<Ntuple<Integer>>();
		axes_ranges = new ArrayList<Ntuple<Integer>>();
		axes_scalings = new ArrayList<Ntuple<Integer>>();
	}

	public String getURL() {
		String s_axes = axesString();
		String s_labels = axesLabelsString();
		String s_positions = axesPositionsString();
		String s_ranges = axesRangesString();
		String s_scalings = axesScalingsString();
	
		return Names.URI_PREFIX + 
			   (chart_type != null ? Names.TYPE + "=" + chart_type + Names.separator : "") + 
			   (title != null ? Names.CHART_TITLE + "=" + title + Names.separator : "") + 
			   (s_axes != null ? s_axes + Names.separator : "") +
			   (s_labels != null ? s_labels + Names.separator : "") + 
			   (s_positions != null ? s_positions + Names.separator : "") + 
			   (s_ranges != null ? s_ranges + Names.separator : "") + 
			   (s_scalings != null ? s_scalings + Names.separator : "") + 
			   Names.CHART_SIZE + "=" + Integer.toString(image_width) + "x" + Integer.toString(image_height) + Names.separator  +  
			   Names.CHART_DATA + "=e:" + Tools.toExtendedFormat(final_data);
	}
	
	public void addAxis(String s) {
		if (s.equals("x") || s.equals("y") || s.equals("r") || s.equals("t"))
			axes.add(s);
	}
	
	public void addAxisLabels(int axis_id, String... labels) {
		Ntuple<String> n = new Ntuple<String>(labels);
		n.setID(axis_id);
		axes_labels.add(n);
	}
	
	public void addAxisPositions(int axis_id, Integer... labels) {
		Ntuple<Integer> n = new Ntuple<Integer>(labels);
		n.setID(axis_id);
		axes_positions.add(n);
	}
	
	public void addAxisRanges(int axis_id, Integer... labels) {
		Ntuple<Integer> n = new Ntuple<Integer>(labels);
		n.setID(axis_id);
		axes_ranges.add(n);
	}
	
	public void addAxisScalings(int axis_id, Integer... labels) {
		Ntuple<Integer> n = new Ntuple<Integer>(labels);
		n.setID(axis_id);
		axes_scalings.add(n);
	}
	
	public void setTitle(String t) {
		title = t;
	}
	
	public String getTitle() {
		return title;
	}
	
	public void setSize(int x, int y) {
		image_width = x;
		image_height = y;
	}
	
	public int getWidth() {
		return image_width;
	}
	
	public int getHeight() {
		return image_height;
	}
	
	private String axesString() {
		int len = axes.size();
		if (len == 0)
			return null;
		String s = axes.get(0);
		for (int i=1; i<len; i++)
			s += "," + axes.get(i);
		return Names.VISIBLE_AXES + "=" + s;
	}
	
	private String axesLabelsString() {
		int len = axes_labels.size();
		if (len == 0)
			return null;
		String s = axes_labels.get(0).toStringBars();
		for (int i=1; i<len; i++) 
			s+= "|" + axes_labels.get(i).toStringBars();
		return Names.AXIS_LABEL + "=" + s;
	}
	
	private String axesPositionsString() {
		int len = axes_positions.size();
		if (len == 0)
			return null;
		String s = axes_positions.get(0).toStringWithID();
		for (int i=1; i<len; i++) 
			s+= "|" + axes_positions.get(i).toStringWithID();
		return Names.AXIS_LABEL_POSITION + "=" + s;
	}
	
	private String axesRangesString() {
		int len = axes_ranges.size();
		if (len == 0)
			return null;
		String s = axes_ranges.get(0).toStringWithID();
		for (int i=1; i<len; i++) 
			s+= "|" + axes_ranges.get(i).toStringWithID();
		return Names.AXIS_RANGE + "=" + s;
	}
	
	private String axesScalingsString() {
		int len = axes_scalings.size();
		if (len == 0)
			return null;
		String s = axes_scalings.get(0).toStringWithID();
		for (int i=1; i<len; i++) 
			s+= "|" + axes_scalings.get(i).toStringWithID();
		return Names.SCALE + "=" + s;
	}

	/**
	 * Google does extended encoding with a max value of 4095, so everything will be shown
	 * proportional to that max. This takes "real" data and adjusts it to the scale, which 
	 * is 0 to max.
	 * @param values
	 * @param max
	 * @return
	 */
	protected int[] adjustForEncoding(int[] values, int max) {
		int len = values.length;
		int[] new_values = new int[len];
		for (int i=0; i<len; i++)
			new_values[i] = Math.round(((float)values[i])/((float)max)*4095);
		return new_values;
	}
}
